﻿#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Reflection;
/// <summary>
/// CSharp类型代码扩展
/// </summary>
public static class ESF_CSharpTypeCodeExtend
{
    /// <summary>
    /// 需要小写的类型代码组
    /// </summary>
    static readonly List<string> mNeedLowerTypeCodes = new List<string>() {
        enESF_CSharpKeyword.voidKeyword.ESF_FirstAttribute<ESF_AliasTooltipAttribute>().alias,
        enESF_CSharpKeyword.systemObjectKeyword.ESF_FirstAttribute<ESF_AliasTooltipAttribute>().alias
    };

    /// <summary>
    /// 获得当前类型的CSharp类型代码
    /// </summary>
    /// <param name="_type">类型</param>
    /// <returns>类型代码</returns>
    public static string GetCSharpTypeCode(this Type _type)
    {
        string result = string.Empty;
        if (_type.IsGenericType)
        {
            List<string> rstArr = new List<string>();
            foreach (var t in _type.GetGenericArguments())
            {
                rstArr.Add(GetCSharpTypeCode(t));
            }
            result = _type.GetGenericTypeDefinition().FullName.Replace($"{enESF_SeparatorSymbol.Backquote.ESF_Symbol()}{rstArr.Count}", $"<{rstArr.ESF_Join(enESF_SeparatorSymbol.Comma)}>");
        }
        else
        {
            Dictionary<string, string> maping = typeof(ESF_enCS2UnityDataType).ESF_SpecialValueToSpecialValue<string, ESF_CSharpCodeAttribute, string>((a) => { return a.csTypeOf.Name; }, (b) => { return b.csType; });
            Type srcType = _type;
            if (_type.IsArray)
            {
                _type = _type.GetElementType();
            }
            if (maping.TryGetValue(_type.Name, out result))
            {
                result = srcType.Name.Replace(_type.Name, result);
            }
            else
            {
                string lower = _type.Name.ToLower();
                if (mNeedLowerTypeCodes.Contains(lower) || mNeedLowerTypeCodes.Contains(_type.FullName))
                {
                    result = lower;
                }
                else if (!string.IsNullOrEmpty(_type.FullName))
                {
                    result = _type.FullName;
                }
                else
                {
                    result = _type.Name;
                }
            }
        }
        return result;
    }

    /// <summary>
    /// 解析类型
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    /// <param name="_type">类型</param>
    /// <param name="_bindFlags">BindingFlags</param>
    /// <param name="_includeInheritInterface">是否包含继承Interface</param>
    /// <returns>解析结果</returns>
    public static List<T> GetResolveType<T>(this Type _type, BindingFlags _bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
        bool _includeInheritInterface = false)
        where T : AbsESF_TypeReflexCodeResolver
    {
        List<T> result = new List<T>();
        Type type = typeof(T);
        var props = _type.GetRecursionProperties(_bindFlags, _includeInheritInterface);
        List<string> propGetSetMethods = new List<string>();
        if (props != null)
        {
            foreach (var p in props)
            {
                var ins = (T)Activator.CreateInstance(type, p);
                if (ins.isValidate)
                {
                    result.Add(ins);
                    if (!string.IsNullOrEmpty(ins.propertyGetMethodNameCode))
                    {
                        propGetSetMethods.Add(ins.propertyGetMethodNameCode);
                    }
                    if (!string.IsNullOrEmpty(ins.propertySetMethodNameCode))
                    {
                        propGetSetMethods.Add(ins.propertySetMethodNameCode);
                    }
                }
            }
        }
        var mets = _type.GetRecursionMethods(_bindFlags, _includeInheritInterface);
        if (mets != null)
        {
            foreach (var m in mets)
            {
                var ins = (T)Activator.CreateInstance(type, m);
                if (!propGetSetMethods.Contains(ins.nameCode) && ins.isValidate)
                {
                    result.Add(ins);
                }
            }
        }
        return result;
    }
}
#endif
